<template>
  <div
    id="townsquare"
    class="square"
    :class="{
      public: grimoire.isPublic,
      spectator: userRole === 'storyteller',
      vote: session.nomination,
    }"
  >
    <ul class="circle" :class="['size-' + players.length]">
      <Player
        v-for="(player, index) in players"
        :key="index"
        :player="player"
        @trigger="handleTrigger(index, $event)"
        :class="{
          from: Math.max(swap, move, nominate) === index,
          swap: swap > -1,
          move: move > -1,
          nominate: nominate > -1,
        }"
      ></Player>
    </ul>

    <!-- 统一的特殊角色面板 -->
    <div
      class="special-roles-panel"
      v-if="(players.length && shouldShowBluffs) || fabled.length"
      ref="specialRoles"
      :class="{ closed: !isSpecialRolesPanelOpen }"
    >
      <h3>
        <span>{{ $t("townSquare.specialRoles") }}</span>
        <font-awesome-icon icon="times-circle" @click.stop="toggleSpecialRolesPanel" />
        <font-awesome-icon icon="plus-circle" @click.stop="toggleSpecialRolesPanel" />
      </h3>
      
      <!-- 传奇角色区域 -->
      <div class="fabled-section" v-if="fabled.length">
        <h4 class="section-title">
          <span>{{ $t("townSquare.fabled") }}</span>
          <font-awesome-icon 
            icon="chevron-down" 
            @click.stop="toggleFabled" 
            :class="{ rotated: !isFabledOpen }"
          />
        </h4>
        <ul v-show="isFabledOpen" class="fabled-list">
          <li
            v-for="(role, index) in fabled"
            :key="'fabled-' + index"
            @click="removeFabled(index)"
          >
            <div
              class="night-order first"
              v-if="nightOrder.get(role).first && grimoire.isNightOrder"
            >
              <em>{{ nightOrder.get(role).first }}.</em>
              <span v-if="role.firstNightReminder">{{
                role.firstNightReminder
              }}</span>
            </div>
            <div
              class="night-order other"
              v-if="nightOrder.get(role).other && grimoire.isNightOrder"
            >
              <em>{{ nightOrder.get(role).other }}.</em>
              <span v-if="role.otherNightReminder">{{
                role.otherNightReminder
              }}</span>
            </div>
            <Token :role="role"></Token>
          </li>
        </ul>
      </div>

      <!-- 恶魔伪装区域 -->
      <div class="bluffs-section" v-if="players.length && shouldShowBluffs">
        <h4 class="section-title">
          <span v-if="userRole === 'storyteller'">{{
            $t("townSquare.otherCharacters")
          }}</span>
          <span v-else>{{ $t("townSquare.demonBluffs") }}</span>
          <font-awesome-icon 
            icon="chevron-down" 
            @click.stop="toggleBluffs" 
            :class="{ rotated: !isBluffsOpen }"
          />
        </h4>
        <ul v-show="isBluffsOpen" class="bluffs-list">
          <li
            v-for="index in bluffSize"
            :key="'bluff-' + index"
            @click="openRoleModal(index * -1)"
            style="cursor: pointer"
          >
            <Token
              :role="bluffs[index - 1]"
              :disable-click="true"
              :allow-parent-click="true"
            ></Token>
          </li>
        </ul>
      </div>
    </div>

    <ReminderModal :player-index="selectedPlayer"></ReminderModal>
    <RoleModal :player-index="selectedPlayer"></RoleModal>
  </div>
</template>

<script>
import { mapGetters, mapState } from "vuex";
import Player from "./Player";
import Token from "./Token";
import ReminderModal from "./modals/ReminderModal";
import RoleModal from "./modals/RoleModal";
import i18n from "../i18n";

export default {
  components: {
    Player,
    Token,
    RoleModal,
    ReminderModal,
  },
  computed: {
    ...mapGetters({ nightOrder: "players/nightOrder" }),
    ...mapState(["grimoire", "roles", "session"]),
    ...mapState("players", ["players", "bluffs", "fabled"]),
    ...mapState("voiceChat", ["users"]),
    // 获取当前用户角色（服务器数据优先）
    userRole() {
      const serverRole = this.users?.get(this.session.playerId)?.role;
      return serverRole || null;
    },
    shouldShowBluffs() {
      // 所有玩家和说书人都可以看到恶魔伪装区域
      return true;
    },
    isCurrentPlayerDemon() {
      // 检查当前玩家是否为恶魔
      const currentPlayer = this.players.find(
        (p) => p.id === this.session.playerId,
      );
      return (
        currentPlayer &&
        currentPlayer.role &&
        currentPlayer.role.team === "demon"
      );
    },
  },
  data() {
    return {
      selectedPlayer: 0,
      bluffSize: 3,
      swap: -1,
      move: -1,
      nominate: -1,
      isBluffsOpen: true,
      isFabledOpen: true,
      isSpecialRolesPanelOpen: true, // 统一面板的展开状态
    };
  },
  methods: {
    $t(key, params = {}) {
      return i18n.t(key, params);
    },
    toggleBluffs() {
      this.isBluffsOpen = !this.isBluffsOpen;
    },
    toggleFabled() {
      this.isFabledOpen = !this.isFabledOpen;
    },
    toggleSpecialRolesPanel() {
      this.isSpecialRolesPanelOpen = !this.isSpecialRolesPanelOpen;
    },
    removeFabled(index) {
      if (this.userRole !== 'storyteller') return;
      this.$store.commit("players/setFabled", { index });
    },
    handleTrigger(playerIndex, [method, params]) {
      if (typeof this[method] === "function") {
        this[method](playerIndex, params);
      } else if (method === "openActionPanel") {
        this.$emit("open-action-panel", playerIndex);
      }
    },
    claimSeat(playerIndex) {
      // 获取服务器端的用户数据
      const currentUser = this.$store.state.voiceChat.users?.get(this.session.playerId);
      const userRole = currentUser?.role || 'spectator';
      
      console.log("🪑 TownSquare.claimSeat 调用:", {
        playerIndex,
        currentPlayerId: this.session.playerId,
        userRole: userRole,
        userPermissions: currentUser?.permissions,
        targetPlayer: this.players[playerIndex],
        targetPlayerId: this.players[playerIndex]?.id
      });

      // 完全依赖服务器端用户数据判断权限，不做本地兜底
      if (!currentUser) {
        console.warn("❌ 等待服务器用户数据...");
        return;
      }
      
      if (userRole === 'storyteller') {
        console.warn("❌ 说书人无法认领座位");
        return;
      }
      
      // 访客可以认领座位（认领后会自动升级为玩家）
      if (userRole === 'spectator') {
        console.log("🎯 访客认领座位，将自动升级为玩家");
      }

      if (this.session.playerId === this.players[playerIndex].id) {
        console.log("🏃 当前玩家离开座位 (vacate)");
        this.$store.commit("session/claimSeat", -1);
      } else {
        console.log(`🪑 认领座位 ${playerIndex}`);
        this.$store.commit("session/claimSeat", playerIndex);
      }
    },
    openReminderModal(playerIndex) {
      this.$store.commit("setSelectedPlayer", playerIndex);
      this.$store.commit("toggleModal", "reminder");
    },
    openRoleModal(playerIndex) {
      console.log("openRoleModal called with playerIndex:", playerIndex);

      // 处理恶魔伪装的负数索引
      if (playerIndex < 0) {
        console.log("处理恶魔伪装，索引:", playerIndex);
        // 恶魔伪装区域，保持负数索引
        this.selectedPlayer = playerIndex;
        this.$store.commit("setSelectedPlayer", playerIndex);
        this.$store.commit("toggleModal", "role");
        console.log("恶魔伪装模态框已打开");
        return;
      }

      // 正常玩家角色选择
      console.log("处理玩家角色选择，索引:", playerIndex);
      const player = this.players[playerIndex];
      if (this.userRole === 'storyteller' && player && player.role.team === "traveler")
        return;
      this.selectedPlayer = playerIndex;
      this.$store.commit("setSelectedPlayer", playerIndex);
      this.$store.commit("toggleModal", "role");
      console.log("玩家角色选择模态框已打开");
    },
    removePlayer(playerIndex) {
      if (this.userRole === 'storyteller' || this.session.lockedVote) return;
      if (
        confirm(
          this.$t("prompts.confirmRemovePlayer", {
            name: this.players[playerIndex].name,
          }),
        )
      ) {
        const { nomination } = this.session;
        if (nomination) {
          if (nomination.includes(playerIndex)) {
            // abort vote if removed player is either nominator or nominee
            this.$store.commit("session/nomination");
          } else if (
            nomination[0] > playerIndex ||
            nomination[1] > playerIndex
          ) {
            // update nomination array if removed player has lower index
            this.$store.commit("session/setNomination", [
              nomination[0] > playerIndex ? nomination[0] - 1 : nomination[0],
              nomination[1] > playerIndex ? nomination[1] - 1 : nomination[1],
            ]);
          }
        }
        this.$store.commit("players/remove", playerIndex);
      }
    },
    swapPlayer(from, to) {
      if (this.userRole === 'storyteller' || this.session.lockedVote) return;
      if (to === undefined) {
        this.cancel();
        this.swap = from;
      } else {
        if (this.session.nomination) {
          // update nomination if one of the involved players is swapped
          const swapTo = this.players.indexOf(to);
          const updatedNomination = this.session.nomination.map((nom) => {
            if (nom === this.swap) return swapTo;
            if (nom === swapTo) return this.swap;
            return nom;
          });
          if (
            this.session.nomination[0] !== updatedNomination[0] ||
            this.session.nomination[1] !== updatedNomination[1]
          ) {
            this.$store.commit("session/setNomination", updatedNomination);
          }
        }
        this.$store.commit("players/swap", [
          this.swap,
          this.players.indexOf(to),
        ]);
        this.cancel();
      }
    },
    movePlayer(from, to) {
      if (this.userRole === 'storyteller' || this.session.lockedVote) return;
      if (to === undefined) {
        this.cancel();
        this.move = from;
      } else {
        if (this.session.nomination) {
          // update nomination if it is affected by the move
          const moveTo = this.players.indexOf(to);
          const updatedNomination = this.session.nomination.map((nom) => {
            if (nom === this.move) return moveTo;
            if (nom > this.move && nom <= moveTo) return nom - 1;
            if (nom < this.move && nom >= moveTo) return nom + 1;
            return nom;
          });
          if (
            this.session.nomination[0] !== updatedNomination[0] ||
            this.session.nomination[1] !== updatedNomination[1]
          ) {
            this.$store.commit("session/setNomination", updatedNomination);
          }
        }
        this.$store.commit("players/move", [
          this.move,
          this.players.indexOf(to),
        ]);
        this.cancel();
      }
    },
    nominatePlayer(from, to) {
      if (this.userRole === 'storyteller' || this.session.lockedVote) return;
      if (to === undefined) {
        this.cancel();
        if (from !== this.nominate) {
          this.nominate = from;
        }
      } else {
        const nomination = [this.nominate, this.players.indexOf(to)];
        this.$store.commit("session/nomination", { nomination });
        this.cancel();
      }
    },
    cancel() {
      this.move = -1;
      this.swap = -1;
      this.nominate = -1;
    },
  },
};
</script>

<style lang="scss">
@use "sass:math";
@import "../vars.scss";

#townsquare {
  width: 100%;
  height: 100%;
  padding: 20px;
  display: flex;
  align-items: center;
  align-content: center;
  justify-content: center;
}

.circle {
  padding: 0;
  width: 100%;
  height: 100%;
  list-style: none;
  margin: 0;

  > li {
    position: absolute;
    left: 50%;
    height: 50%;
    transform-origin: 0 100%;
    pointer-events: none;

    &:hover {
      z-index: 25 !important;
    }

    > .player {
      margin-left: -50%;
      width: 100%;
      pointer-events: all;
    }
    > .reminder {
      margin-left: -25%;
      width: 50%;
      pointer-events: all;
    }
  }
}

@mixin on-circle($item-count) {
  $angle: math.div(360, $item-count);
  $rot: 0;

  // rotation and tooltip placement
  @for $i from 1 through $item-count {
    &:nth-child(#{$i}) {
      transform: rotate($rot * 1deg);
      @if $i - 1 <= math.div($item-count, 2) {
        // first half of players
        z-index: $item-count - $i + 1;
        // open menu on the left
        .player > .menu {
          left: auto;
          right: 110%;
          margin-right: 15px;
          &:before {
            border-left-color: black;
            border-right-color: transparent;
            right: auto;
            left: 100%;
          }
        }
        .fold-enter-active,
        .fold-leave-active {
          transform-origin: right center;
        }
        .fold-enter,
        .fold-leave-to {
          transform: perspective(200px) rotateY(-90deg);
        }
        // show ability tooltip on the left
        .ability {
          right: 120%;
          left: auto;
          &:before {
            border-right-color: transparent;
            border-left-color: black;
            right: auto;
            left: 100%;
          }
        }
        .pronouns {
          left: 110%;
          right: auto;
          &:before {
            border-left-color: transparent;
            border-right-color: black;
            left: auto;
            right: 100%;
          }
        }
      } @else {
        // second half of players
        z-index: $i - 1;
      }

      > * {
        transform: rotate($rot * -1deg);
      }

      // animation cascade
      .life,
      .token,
      .shroud,
      .night-order,
      .seat {
        animation-delay: ($i - 1) * 50ms;
        transition-delay: ($i - 1) * 50ms;
      }

      // move reminders closer to the sides of the circle
      $q: math.div($item-count, 4);
      $x: $i - 1;
      @if $x < $q or ($x >= math.div($item-count, 2) and $x < $q * 3) {
        .player {
          margin-bottom: -10% + 20% * (1 - math.div($x % $q, $q));
        }
      } @else {
        .player {
          margin-bottom: -10% + 20% * math.div($x % $q, $q);
        }
      }
    }
    $rot: $rot + $angle;
  }
}

@for $i from 1 through 20 {
  .circle.size-#{$i} > li {
    @include on-circle($item-count: $i);
  }
}

/***** Special Roles Panel (Unified) *******/
#townsquare > .special-roles-panel {
  position: absolute;
  top: 10px;
  left: 10px;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 10px;
  border: 3px solid black;
  filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.5));
  transform-origin: top left;
  transform: scale(1);
  opacity: 1;
  transition: all 200ms ease-in-out;
  z-index: 50;
  max-width: 350px; // 更宽的统一面板
  min-height: 80px;
  max-height: 500px; // 更高以容纳两个区域
  
  // 确保提示框不被面板边界裁剪
  overflow: visible;
  
  // 收起状态
  &.closed {
    height: 40px;
    overflow: hidden;
    
    .fabled-section,
    .bluffs-section {
      display: none;
    }
  }
}

// 统一面板内部样式
#townsquare > .special-roles-panel {
  // 主标题样式
  > h3 {
    margin: 5px 1vh 0;
    display: flex;
    align-items: center;
    align-content: center;
    justify-content: center;
    border-bottom: 1px solid rgba(255, 255, 255, 0.2);
    padding-bottom: 8px;
    margin-bottom: 12px;
    
    span {
      flex-grow: 1;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: 16px;
      font-weight: bold;
    }
    
    svg {
      cursor: pointer;
      flex-grow: 0;
      margin-left: 1vh;
      
      &.fa-times-circle {
        display: block;
      }
      &.fa-plus-circle {
        display: none;
      }
      &:hover path {
        fill: url(#demon);
        stroke-width: 30px;
        stroke: white;
      }
    }
  }

  // 收起状态时的图标切换
  &.closed {
    > h3 svg {
      &.fa-times-circle {
        display: none;
      }
      &.fa-plus-circle {
        display: block;
      }
    }
  }

  // 区域分隔样式
  .fabled-section,
  .bluffs-section {
    margin-bottom: 16px;
    
    &:last-child {
      margin-bottom: 8px;
    }

    .section-title {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin: 0 0 8px 0;
      padding: 4px 8px;
      background: rgba(255, 255, 255, 0.1);
      border-radius: 6px;
      cursor: pointer;
      transition: background-color 0.2s;

      &:hover {
        background: rgba(255, 255, 255, 0.15);
      }

      span {
        font-size: 14px;
        font-weight: bold;
        color: #fff;
      }

      svg {
        transition: transform 0.2s;
        color: rgba(255, 255, 255, 0.7);
        
        &.rotated {
          transform: rotate(-90deg);
        }
        
        &:hover {
          color: #fff;
        }
      }
    }

    // 角色列表样式
    ul {
      display: flex;
      align-items: flex-start;
      justify-content: flex-start;
      flex-wrap: wrap;
      padding: 8px;
      gap: 8px;
      max-height: 200px; // 每个区域的最大高度
      overflow-y: auto;
      overflow-x: visible; // 确保提示框可以水平延伸
      
      // 确保提示框不被裁剪
      position: relative;
      
      // Firefox 滚动条样式
      scrollbar-width: thin;
      scrollbar-color: rgba(255, 215, 0, 0.8) rgba(255, 255, 255, 0.1);
      
      // Webkit 滚动条样式 (Chrome, Safari, Edge)
      &::-webkit-scrollbar {
        width: 8px;
      }
      
      &::-webkit-scrollbar-track {
        background: rgba(255, 255, 255, 0.1);
        border-radius: 4px;
        margin: 4px 0;
      }
      
      &::-webkit-scrollbar-thumb {
        background: linear-gradient(180deg, 
          rgba(255, 215, 0, 0.8) 0%, 
          rgba(255, 165, 0, 0.8) 50%, 
          rgba(255, 140, 0, 0.8) 100%
        );
        border-radius: 4px;
        border: 1px solid rgba(255, 255, 255, 0.2);
        transition: all 0.3s ease;
        
        &:hover {
          background: linear-gradient(180deg, 
            rgba(255, 215, 0, 1) 0%, 
            rgba(255, 165, 0, 1) 50%, 
            rgba(255, 140, 0, 1) 100%
          );
          box-shadow: 0 0 8px rgba(255, 215, 0, 0.5);
        }
        
        &:active {
          background: linear-gradient(180deg, 
            rgba(255, 140, 0, 1) 0%, 
            rgba(255, 165, 0, 1) 50%, 
            rgba(255, 215, 0, 1) 100%
          );
        }
      }
      
      &::-webkit-scrollbar-corner {
        background: rgba(255, 255, 255, 0.1);
      }
      
      // 增强滚动体验
      scroll-behavior: smooth;
      -webkit-overflow-scrolling: touch;
      
      li {
        width: 10vh; // 适中的角色图标大小
        height: 10vh;
        margin: 0;
        display: inline-block;
        transition: all 250ms;
        flex-shrink: 0;
        position: relative; // 为提示框定位提供基准
        
        // 确保悬停时的提示框显示在最上层
        &:hover {
          z-index: 1000; // 远高于面板的z-index(50)
          position: relative;
        }
        
        // Token组件内的提示框样式
        .token {
          position: relative;
          
          // 当出现提示框时，确保不被容器裁剪
          &:hover {
            overflow: visible;
            z-index: 1001;
            position: relative;
          }
        }
      }
    }
  }

  // 传奇角色区域特殊样式
  .fabled-section {
    .section-title span {
      color: #FFD700; // 金色，突出传奇角色
    }
    
    // 传奇角色专用滚动条 - 金色主题
    ul {
      // Firefox 传奇角色滚动条
      scrollbar-color: rgba(255, 215, 0, 0.9) rgba(255, 255, 255, 0.15) !important;
      
      // Webkit 传奇角色滚动条
      &::-webkit-scrollbar-thumb {
        background: linear-gradient(180deg, 
          rgba(255, 215, 0, 0.8) 0%, 
          rgba(255, 165, 0, 0.8) 50%, 
          rgba(255, 140, 0, 0.8) 100%
        ) !important;
        
        &:hover {
          background: linear-gradient(180deg, 
            rgba(255, 215, 0, 1) 0%, 
            rgba(255, 165, 0, 1) 50%, 
            rgba(255, 140, 0, 1) 100%
          ) !important;
          box-shadow: 0 0 8px rgba(255, 215, 0, 0.6) !important;
        }
      }
    }
  }

  // 恶魔伪装区域特殊样式
  .bluffs-section {
    .section-title span {
      color: #FF6B6B; // 红色，突出恶魔伪装
    }
    
    // 恶魔伪装专用滚动条 - 红色主题
    ul {
      // Firefox 恶魔伪装滚动条
      scrollbar-color: rgba(255, 107, 107, 0.9) rgba(255, 255, 255, 0.15) !important;
      
      // Webkit 恶魔伪装滚动条
      &::-webkit-scrollbar-thumb {
        background: linear-gradient(180deg, 
          rgba(255, 107, 107, 0.8) 0%, 
          rgba(220, 20, 60, 0.8) 50%, 
          rgba(178, 34, 34, 0.8) 100%
        ) !important;
        
        &:hover {
          background: linear-gradient(180deg, 
            rgba(255, 107, 107, 1) 0%, 
            rgba(220, 20, 60, 1) 50%, 
            rgba(178, 34, 34, 1) 100%
          ) !important;
          box-shadow: 0 0 8px rgba(255, 107, 107, 0.6) !important;
        }
      }
    }
  }
}

// 确保角色提示框在特殊角色面板中正确显示
#townsquare > .special-roles-panel {
  // 全局提示框样式 - 确保最高层级显示
  .tooltip,
  .token-tooltip,
  .role-tooltip,
  [class*="tooltip"] {
    z-index: 9999 !important;
    position: fixed !important; // 使用fixed定位，相对于视口
    pointer-events: none;
    
    // 确保提示框内容完整显示
    white-space: normal;
    max-width: 300px;
    word-wrap: break-word;
  }
  
  // Token组件内的任何提示元素
  .token {
    // 当悬停时，确保提示框元素获得最高优先级
    &:hover {
      .tooltip,
      .role-ability,
      .role-description,
      [data-tooltip],
      [title] {
        z-index: 9999 !important;
        position: fixed !important;
      }
    }
  }
}

#townsquare.public > .special-roles-panel .bluffs-section {
  opacity: 0;
  transform: scale(0.1);
}

// 统一面板的响应式调整
@media (max-width: 1200px) {
  #townsquare > .special-roles-panel {
    max-width: calc(100vw - 40px) !important;
    
    .fabled-section ul li,
    .bluffs-section ul li {
      width: 9vh !important;
      height: 9vh !important;
    }
    
    // 中等屏幕滚动条调整
    .fabled-section ul,
    .bluffs-section ul {
      &::-webkit-scrollbar {
        width: 6px !important;
      }
    }
  }
}

@media (max-width: 768px) {
  #townsquare > .special-roles-panel {
    left: 10px !important;
    max-width: calc(100vw - 30px) !important;
    
    .fabled-section ul li,
    .bluffs-section ul li {
      width: 8vh !important;
      height: 8vh !important;
    }
    
    // 移动端减小区域间距
    .fabled-section,
    .bluffs-section {
      margin-bottom: 12px;
    }
    
    // 调整区域标题字体
    .section-title span {
      font-size: 13px !important;
    }
    
    // 移动端滚动条调整 - 更细的滚动条
    .fabled-section ul,
    .bluffs-section ul {
      &::-webkit-scrollbar {
        width: 4px !important;
      }
      
      &::-webkit-scrollbar-track {
        background: rgba(255, 255, 255, 0.05) !important;
        margin: 2px 0 !important;
      }
      
      // 移动端使用更简洁的渐变
      &::-webkit-scrollbar-thumb {
        border: none !important;
        border-radius: 2px !important;
      }
    }
  }
}

@media (max-width: 480px) {
  #townsquare > .special-roles-panel {
    left: 5px !important;
    max-width: calc(100vw - 20px) !important;
    
    .fabled-section ul li,
    .bluffs-section ul li {
      width: 7vh !important;
      height: 7vh !important;
    }
    
    // 超小屏幕进一步压缩
    .fabled-section,
    .bluffs-section {
      margin-bottom: 8px;
      
      ul {
        gap: 6px !important;
        padding: 6px !important;
        
        // 超小屏幕隐藏滚动条，使用触摸滚动
        &::-webkit-scrollbar {
          display: none !important;
        }
        
        // 启用平滑滚动
        scroll-behavior: smooth;
        -webkit-overflow-scrolling: touch;
      }
    }
    
    // 主标题调整
    > h3 span {
      font-size: 14px !important;
    }
    
    .section-title {
      padding: 3px 6px !important;
      
      span {
        font-size: 12px !important;
      }
    }
  }
}

.fabled ul li .token:before {
  content: " ";
  opacity: 0;
  transition: opacity 250ms;
  background-image: url("../assets/icons/x.png");
  z-index: 2;
}

/**** Night reminders ****/
.night-order {
  position: absolute;
  width: 100%;
  cursor: pointer;
  opacity: 1;
  transition: opacity 200ms;
  display: flex;
  top: 0;
  align-items: center;
  pointer-events: none;

  &:after {
    content: " ";
    display: block;
    padding-top: 100%;
  }

  #townsquare.public & {
    opacity: 0;
    pointer-events: none;
  }

  &:hover ~ .token .ability {
    opacity: 0;
  }

  span {
    display: flex;
    position: absolute;
    padding: 5px 10px 5px 30px;
    width: 350px;
    z-index: 25;
    font-size: 70%;
    background: rgba(0, 0, 0, 0.5);
    border-radius: 10px;
    border: 3px solid black;
    filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.5));
    text-align: left;
    align-items: center;
    opacity: 0;
    transition: opacity 200ms ease-in-out;

    &:before {
      transform: rotate(-90deg);
      transform-origin: center top;
      left: -98px;
      top: 50%;
      font-size: 100%;
      position: absolute;
      font-weight: bold;
      text-align: center;
      width: 200px;
    }

    &:after {
      content: " ";
      border: 10px solid transparent;
      width: 0;
      height: 0;
      position: absolute;
    }
  }

  &.first span {
    right: 120%;
    background: linear-gradient(
      to right,
      $townsfolk 0%,
      rgba(0, 0, 0, 0.5) 20%
    );
    &:before {
      content: "First Night";
    }
    &:after {
      border-left-color: $townsfolk;
      margin-left: 3px;
      left: 100%;
    }
  }

  &.other span {
    left: 120%;
    background: linear-gradient(to right, $demon 0%, rgba(0, 0, 0, 0.5) 20%);
    &:before {
      content: "Other Nights";
    }
    &:after {
      right: 100%;
      margin-right: 3px;
      border-right-color: $demon;
    }
  }

  em {
    font-style: normal;
    position: absolute;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 3px solid black;
    filter: drop-shadow(0 0 6px rgba(0, 0, 0, 0.5));
    font-weight: bold;
    opacity: 1;
    pointer-events: all;
    transition: opacity 200ms;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 3;
  }

  &.first em {
    left: -10%;
    background: linear-gradient(180deg, rgba(0, 0, 0, 1) 0%, $townsfolk 100%);
  }

  &.other em {
    right: -10%;
    background: linear-gradient(180deg, rgba(0, 0, 0, 1) 0%, $demon 100%);
  }

  em:hover + span {
    opacity: 1;
  }

  // adjustment for fabled
  .fabled &.first {
    span {
      right: auto;
      left: 40px;
      &:after {
        left: auto;
        right: 100%;
        margin-left: 0;
        margin-right: 3px;
        border-left-color: transparent;
        border-right-color: $townsfolk;
      }
    }
  }
}

#townsquare:not(.spectator) .fabled ul li:hover .token:before {
  opacity: 1;
}
</style>
